home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / mint104s.zoo / mint.src / util.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  13KB  |  641 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /*
  8.  * misc. utility routines
  9.  */
  10.  
  11. #include "mint.h"
  12.  
  13. /*
  14.  * given an address, find the corresponding memory region in this program's
  15.  * memory map
  16.  */
  17.  
  18. MEMREGION *
  19. addr2mem(a)
  20.     virtaddr a;
  21. {
  22.     int i;
  23.  
  24.     for (i = 0; i < curproc->num_reg; i++) {
  25.         if (a == curproc->addr[i])
  26.             return curproc->mem[i];
  27.     }
  28.     return 0;
  29. }
  30.  
  31. /*
  32.  * given a pid, return the corresponding process
  33.  */
  34.  
  35. PROC *
  36. pid2proc(pid)
  37.     int pid;
  38. {
  39.     PROC *p;
  40.  
  41.     for (p = proclist; p; p = p->gl_next) {
  42.         if (p->pid == pid)
  43.             return p;
  44.     }
  45.     return 0;
  46. }
  47.  
  48. /*
  49.  * return a new pid
  50.  */
  51.  
  52. int
  53. newpid()
  54. {
  55.     static int _maxpid = 1;
  56.     int i;
  57. #ifndef NDEBUG
  58.     int j = 0;
  59. #endif
  60.  
  61.     do {
  62.         i = _maxpid++;
  63.         if (_maxpid >= 1000) _maxpid = 1;
  64.         assert(j++ < 1000);
  65.     } while (pid2proc(i));
  66.  
  67.     return i;
  68. }
  69.  
  70. /*
  71.  * zero out a block of memory, quickly; the block must be word-aligned,
  72.  * and should be long-aligned for speed reasons
  73.  */
  74.  
  75. void
  76. zero(place, size)
  77.     char *place;
  78.     long size;
  79. {
  80.     long cruft;
  81.  
  82.     cruft = size % 256;    /* quickzero does 256 byte blocks */
  83.     size = size / 256;
  84.     while (cruft > 0) {
  85.         *place++ = 0;
  86.         cruft--;
  87.     }
  88.     if (size > 0) {
  89.         quickzero(place, size);
  90.     }
  91. }
  92.  
  93. #ifdef JUNK_MEM
  94. void
  95. fillwjunk(place, size)
  96.     long *place;
  97.     long size;
  98. {
  99.     while (size > 0) {
  100.         *place++ = size;
  101.         size -= 4;
  102.     }
  103. }
  104. #endif
  105.  
  106. /*
  107.  * kernel memory allocation routines
  108.  */
  109.  
  110. #define KERMEM_THRESHOLD QUANTUM-8
  111. #define KMAGIC ((MEMREGION *)0x87654321L)
  112. #define NKMAGIC 0x19870425L
  113.  
  114. void * ARGS_ON_STACK 
  115. kmalloc(size)
  116.     long size;
  117. {
  118.     MEMREGION *m = 0;
  119.     MEMREGION **p;
  120.     long *lp;
  121.  
  122.     /*
  123.      * increase size by two pointers' worth: the first contains
  124.      * a pointer to the region descriptor for this block, and the
  125.      * second contains KMAGIC.  If the block came from nalloc,
  126.      * then they both contain NKMAGIC.
  127.      */
  128.     size += sizeof(m) + sizeof(m);
  129. /*
  130.  * for small requests, we use nalloc first
  131.  */
  132. tryagain:
  133.     if (size < KERMEM_THRESHOLD) {
  134.         lp = nalloc(size);
  135.         if (lp) {
  136.         *lp++ = NKMAGIC;
  137.         *lp++ = NKMAGIC;
  138.         TRACELOW(("kmalloc(%lx) -> (nalloc) %lx",size,lp));
  139.         return lp;
  140.         }
  141.         else {
  142.         DEBUG(("kmalloc(%lx): nalloc is out of memory",size));
  143.  
  144.     /* If this is commented out, then we fall through to try_getregion */
  145.         if (0 == (m = get_region(alt, QUANTUM, PROT_S))) {
  146.             if (0 == (m = get_region(core, QUANTUM, PROT_S))) {
  147.             DEBUG(("No memory for another arena"));
  148.             goto try_getregion;
  149.             }
  150.         }
  151.         nalloc_arena_add((void *)m->loc,QUANTUM);
  152.         m = 0;
  153.         goto tryagain;
  154.         }
  155.     }
  156.  
  157. try_getregion:
  158.     m = get_region(alt, size, PROT_S);
  159.  
  160.     if (!m) m = get_region(core, size, PROT_S);
  161.  
  162.     if (m) {
  163.         p = (MEMREGION **)m->loc;
  164.         *p++ = KMAGIC;
  165.         *p++ = m;
  166.         TRACELOW(("kmalloc(%lx) -> (get_region) %lx",size,p));
  167.         return (void *)p;
  168.     }
  169.     else {
  170.         TRACELOW(("kmalloc(%lx) -> (fail)",size));
  171. #if 0
  172.         /* this is a serious offense; I want to hear about it */
  173.         /* maybe Allan wanted to hear about it, but ordinary users
  174.          * won't! -- ERS
  175.          */
  176.         NALLOC_DUMP();
  177.         BIG_MEM_DUMP(0,0);
  178. #endif
  179.         return 0;
  180.     }
  181. }
  182.  
  183. /* allocate from ST memory only */
  184.  
  185. void *
  186. kcore(size)
  187.     long size;
  188. {
  189.     MEMREGION *m;
  190.     MEMREGION **p;
  191.  
  192.     size += sizeof(m) + sizeof (m);
  193.     m = get_region(core, size, PROT_S);
  194.  
  195.     if (m) {
  196.         p = (MEMREGION **)m->loc;
  197.         *p++ = KMAGIC;
  198.         *p++ = m;
  199.         return (void *)p;
  200.     }
  201.     else {
  202.         return 0;
  203.     }
  204. }
  205.  
  206. void ARGS_ON_STACK 
  207. kfree(place)
  208.     void *place;
  209. {
  210.     MEMREGION **p;
  211.     MEMREGION *m;
  212.  
  213.     TRACELOW(("kfree(%lx)",place));
  214.  
  215.     if (!place) return;
  216.     p = place;
  217.     p -= 2;
  218.     if (*p == (MEMREGION *)NKMAGIC) {
  219.         nfree(p);
  220.         return;
  221.     }
  222.     else if (*p++ != KMAGIC) {
  223.         FATAL("kfree: memory not allocated by kmalloc");
  224.     }
  225.     m = *p;
  226.     if (--m->links != 0) {
  227.         FATAL("kfree: block has %d links", m->links);
  228.     }
  229.     free_region(m);
  230. }
  231.  
  232. /*
  233.  * "user" memory allocation routines; the kernel can use these to
  234.  * allocate/free memory that will be attached in some way to a process
  235.  * (and freed automatically when the process exits)
  236.  */
  237. void * ARGS_ON_STACK 
  238. umalloc(size)
  239.     long size;
  240. {
  241.     return (void *)m_xalloc(size, 3);
  242. }
  243.  
  244. void ARGS_ON_STACK 
  245. ufree(block)
  246.     void *block;
  247. {
  248.     (void)m_free((virtaddr)block);
  249. }
  250.  
  251. /*
  252.  * convert a time in milliseconds to a GEMDOS style date/time
  253.  * timeptr[0] gets the time, timeptr[1] the date.
  254.  * BUG/FEATURE: in the conversion, it is assumed that all months have
  255.  * 30 days and all years have 360 days.
  256.  */
  257.  
  258. void ARGS_ON_STACK 
  259. ms_time(ms, timeptr)
  260.     ulong ms;
  261.     short *timeptr;
  262. {
  263.     ulong secs;
  264.     short tsec, tmin, thour;
  265.     short tday, tmonth, tyear;
  266.  
  267.     secs = ms / 1000;
  268.     tsec = secs % 60;
  269.     secs /= 60;        /* secs now contains # of minutes */
  270.     tmin = secs % 60;
  271.     secs /= 60;        /* secs now contains # of hours */
  272.     thour = secs % 24;
  273.     secs /= 24;        /* secs now contains # of days */
  274.     tday = secs % 30;
  275.     secs /= 30;
  276.     tmonth = secs % 12;
  277.     tyear = secs / 12;
  278.     *timeptr++ = (thour << 11) | (tmin << 5) | (tsec >> 1);
  279.     *timeptr = (tyear << 9) | ((tmonth + 1) << 5) | (tday+1);
  280. }
  281.  
  282. /*
  283.  * unixtim(time, date): convert a Dos style (time, date) pair into
  284.  * a Unix time (seconds from midnight Jan 1., 1970)
  285.  */
  286.  
  287. static int
  288. mth_start[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
  289.  
  290. long ARGS_ON_STACK 
  291. unixtim(time, date)
  292.     unsigned time, date;
  293. {
  294.     int sec, min, hour;
  295.     int mday, mon, year;
  296.     long y, s;
  297.  
  298.     sec = (time & 31) << 1;
  299.     min = (time >> 5) & 63;
  300.     hour = (time >> 11) & 31;
  301.     mday = date & 31;
  302.     mon = ((date >> 5) & 15) - 1;
  303.     year = 80 + ((date >> 9) & 255);
  304.  
  305. /* calculate tm_yday here */
  306.     y = (mday - 1) + mth_start[mon] + /* leap year correction */
  307.         ( ( (year % 4) != 0 ) ? 0 : (mon > 1) );
  308.  
  309.     s = (sec) + (min * 60L) + (hour * 3600L) +
  310.         (y * 86400L) + ((year - 70) * 31536000L) +
  311.         ((year - 69)/4) * 86400L;
  312.  
  313.     return s;
  314. }
  315.  
  316. /* convert a Unix time into a DOS time. The longword returned contains
  317.    the time word first, then the date word.
  318.    BUG: we completely ignore any time zone information.
  319. */
  320. #define SECS_PER_MIN    (60L)
  321. #define SECS_PER_HOUR   (3600L)
  322. #define SECS_PER_DAY    (86400L)
  323. #define SECS_PER_YEAR   (31536000L)
  324. #define SECS_PER_LEAPYEAR (SECS_PER_DAY + SECS_PER_YEAR)
  325.  
  326. static int
  327. days_per_mth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  328.  
  329. long ARGS_ON_STACK 
  330. dostim(t)
  331.     long t;
  332. {
  333.         unsigned long time, date;
  334.     int tm_hour, tm_min, tm_sec;
  335.     int tm_year, tm_mon, tm_mday;
  336.     int i;
  337.  
  338.     if (t <= 0) return 0;
  339.  
  340.     tm_year = 70;
  341.     while (t >= SECS_PER_YEAR) {
  342.         if ((tm_year & 0x3) == 0) {
  343.             if (t < SECS_PER_LEAPYEAR)
  344.                 break;
  345.             t -= SECS_PER_LEAPYEAR;
  346.         } else {
  347.             t -= SECS_PER_YEAR;
  348.         }
  349.         tm_year++;
  350.     }
  351.     tm_mday = (int)(t/SECS_PER_DAY);
  352.         days_per_mth[1] = (tm_year & 0x3) ? 28 : 29;
  353.         for (i = 0; tm_mday >= days_per_mth[i]; i++)
  354.                 tm_mday -= days_per_mth[i];
  355.         tm_mon = i+1;
  356.     tm_mday++;
  357.         t = t % SECS_PER_DAY;
  358.         tm_hour = (int)(t/SECS_PER_HOUR);
  359.         t = t % SECS_PER_HOUR;
  360.         tm_min = (int)(t/SECS_PER_MIN);
  361.         tm_sec = (int)(t % SECS_PER_MIN);
  362.  
  363.     if (tm_year < 80) {
  364.         tm_year = 80;
  365.         tm_mon = tm_mday = 1;
  366.         tm_hour = tm_min = tm_sec = 0;
  367.     }
  368.  
  369.     time = (tm_hour << 11) | (tm_min << 5) | (tm_sec >> 1);
  370.     date = ((tm_year - 80) & 0x7f) << 9;
  371.     date |= ((tm_mon) << 5) | (tm_mday);
  372.     return (time << 16) | date;
  373. }
  374.  
  375. /*
  376.  * Case insensitive string comparison. note that this only returns
  377.  * 0 (match) or nonzero (no match), and that the returned value
  378.  * is not a reliable indicator of any "order".
  379.  */
  380.  
  381. int ARGS_ON_STACK 
  382. strnicmp(str1, str2, len)
  383.     register const char *str1, *str2;
  384.     register int len;
  385. {
  386.     register char c1, c2;
  387.  
  388.     do {
  389.         c1 = *str1++; if (isupper(c1)) c1 = tolower(c1);
  390.         c2 = *str2++; if (isupper(c2)) c2 = tolower(c2);
  391.     } while (--len >= 0 && c1 && c1 == c2);
  392.  
  393.     if (len < 0 || c1 == c2)
  394.         return 0;
  395.     return c1 - c2;
  396. }
  397.  
  398. int ARGS_ON_STACK 
  399. stricmp(str1, str2)
  400.     const char *str1, *str2;
  401. {
  402.     return strnicmp(str1, str2, 0x7fff);
  403. }
  404.  
  405.  
  406. /*
  407.  * string utilities: strlwr() conv